using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace Polymod
{
    public class NotificationModel<T> : ModelBase<T>, INotifyPropertyChanged, INotify
    {
        private IDictionary<string, string[]> _notifications;
        IParentModelInfo _parent;

        /// <summary>
        /// Gets Parent
        /// </summary>
        public IParentModelInfo Parent
        {
            get { return _parent; }
        }

        public override void Set(string name, object value)
        {
            if (base.Get(name) != value)
            {
                base.Set(name, value);
                OnPropertyChanged(name);
            }
        }
        public override void Initialize(object value, IDictionary<string, object> state)
        {
            base.Initialize(value, state);

            _notifications = (IDictionary<string, string[]>)state[Constants.AffectedPropertyRegistry];
            _parent = state[Constants.ParentModelInfo] as IParentModelInfo;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string property)
        {
            var local = this.PropertyChanged;
            if (local != null)
            {
                local(this, new System.ComponentModel.PropertyChangedEventArgs(property));

                //Notify all other affected properties.
                foreach (var affectedProperty in _notifications.GetOrEmpty(property))
                {
                    OnPropertyChanged(affectedProperty);
                }
            }

            //Tell the parent model (if any) that this property has changed.
            NotifyParent(property);
        }

        private void NotifyParent(string propertyName)
        {
            if (_parent != null)
            {
                var notifyParent = _parent.Parent as INotify;
                if (notifyParent != null)
                {
                    notifyParent.NotifyChanged(_parent.MemberName + "." + propertyName);
                }
            }
        }

        void INotify.NotifyChanged(string propertyName)
        {
            OnPropertyChanged(propertyName);
        }
    }
}
